﻿/*
 * Handles Rendering of 3D Planets.
 * 3D Models from: http://sketchup.google.com/3dwarehouse/
 * Author: Bachir
 * 
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;

namespace Homebound
{
    public class Planets
    {
        public GraphicsDeviceManager graphics;
        //ContentManager content;
        public Model moon, swamp, dry, green;
        public Matrix view, projection;
        public List<Matrix> world, initial;
        public List<Vector3> currentPosition/*, previousPosition*/;
        public float idleRotation = 0.02f, activeRotation = 0.005f, incline = MathHelper.ToRadians(20);
        public float idleScale = 1.00f, activeScale = 1.40f, modSpeed = 0.01f;
        public List<float> currentScale, currentRotation;
        public State state;
        public List<bool> lightUp;
        public Vector3 lightDirection = Vector3.Normalize(new Vector3(0, 0, -1));

        public Planets(GraphicsDeviceManager graphics, ContentManager content, State state)
        {
            this.graphics = graphics;
            this.state = state;
            view = Matrix.CreateLookAt(new Vector3(0, 0, 80), new Vector3(0, 0, 0), Vector3.UnitY);
            float aspect = (float)this.graphics.PreferredBackBufferWidth / (float)this.graphics.PreferredBackBufferHeight;
            projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), aspect, 0.1f, 250f);
            green = content.Load<Model>("Models/green");
            moon = content.Load<Model>("Models/moon");
            swamp = content.Load<Model>("Models/swamp");
            dry = content.Load<Model>("Models/dry");
            currentPosition = new List<Vector3>();
            //previousPosition = new List<Vector3>();
            world = new List<Matrix>();
            initial = new List<Matrix>();
            currentScale = new List<float>();
            currentRotation = new List<float>();
            lightUp = new List<bool>();
            currentPosition.Add(new Vector3(30, -10, 10));
            currentPosition.Add(new Vector3(-20, 15, 0));
            currentPosition.Add(new Vector3(25, 0, 0));
            currentPosition.Add(new Vector3(-25, -15, 0));
            currentScale.Add(1.00f);
            currentScale.Add(1.00f);
            currentScale.Add(1.00f);
            currentRotation.Add(0);
            currentRotation.Add(0);
            currentRotation.Add(0);
            lightUp.Add(false);
            lightUp.Add(false);
            lightUp.Add(false);
            //previousPosition.Add(currentPosition[0]);
            //previousPosition.Add(currentPosition[1]);
            //previousPosition.Add(currentPosition[2]);
            //previousPosition.Add(currentPosition[3]);
            world.Add(Matrix.CreateScale(0.20f) * Matrix.CreateRotationX(MathHelper.ToRadians(90)) * Matrix.CreateRotationZ(incline) * Matrix.CreateTranslation(currentPosition[0]));
            world.Add(Matrix.CreateScale(0.20f) * Matrix.CreateRotationX(MathHelper.ToRadians(90)) * Matrix.CreateRotationZ(incline) * Matrix.CreateTranslation(currentPosition[1]));
            world.Add(Matrix.CreateScale(0.20f) * Matrix.CreateRotationX(MathHelper.ToRadians(90)) * Matrix.CreateRotationZ(incline) * Matrix.CreateTranslation(currentPosition[2]));
            world.Add(Matrix.CreateScale(0.20f) * Matrix.CreateRotationX(MathHelper.ToRadians(90)) * Matrix.CreateRotationZ(incline) * Matrix.CreateTranslation(currentPosition[3]));
            initial.Add(world[0]);
            initial.Add(world[1]);
            initial.Add(world[2]);
            initial.Add(world[3]);
        }

        public void UpdateLevelPlanets(GameTime gameTime)
        {
            switch (state.selectedChoice)
            {
                case 0:
                    if (currentScale[0] < activeScale)
                        currentScale[0] += modSpeed;
                    currentRotation[0] += activeRotation;
                    if (currentScale[1] > idleScale)
                        currentScale[1] -= modSpeed;
                    currentRotation[1] += idleRotation;
                    if (currentScale[2] > idleScale)
                        currentScale[2] -= modSpeed;
                    currentRotation[2] += idleRotation;
                    if (lightUp[0] == false)
                    {
                        lightUp[0] = true;
                        lightUp[1] = false;
                        lightUp[2] = false;
                    }
                    break;
                case 1:
                    if (currentScale[1] < activeScale)
                        currentScale[1] += modSpeed;
                    currentRotation[1] += activeRotation;
                    if (currentScale[0] > idleScale)
                        currentScale[0] -= modSpeed;
                    currentRotation[0] += idleRotation;
                    if (currentScale[2] > idleScale)
                        currentScale[2] -= modSpeed;
                    currentRotation[2] += idleRotation;
                    if (lightUp[1] == false)
                    {
                        lightUp[0] = false;
                        lightUp[1] = true;
                        lightUp[2] = false;
                    }
                    break;
                case 2:
                    if (currentScale[2] < activeScale)
                        currentScale[2] += modSpeed;
                    currentRotation[2] += activeRotation;
                    if (currentScale[1] > idleScale)
                        currentScale[1] -= modSpeed;
                    currentRotation[1] += idleRotation;
                    if (currentScale[0] > idleScale)
                        currentScale[0] -= modSpeed;
                    currentRotation[0] += idleRotation;
                    if (lightUp[2] == false)
                    {
                        lightUp[0] = false;
                        lightUp[1] = false;
                        lightUp[2] = true;
                    }
                    break;
            }
            world[1] = initial[1] * Matrix.CreateTranslation(-currentPosition[1]) * Matrix.CreateRotationZ(-incline) * Matrix.CreateScale(currentScale[0]) * Matrix.CreateRotationY(currentRotation[0]) * Matrix.CreateRotationZ(incline) * Matrix.CreateTranslation(currentPosition[1]);
            world[2] = initial[2] * Matrix.CreateTranslation(-currentPosition[2]) * Matrix.CreateRotationZ(-incline) * Matrix.CreateScale(currentScale[1]) * Matrix.CreateRotationY(currentRotation[1]) * Matrix.CreateRotationZ(incline) * Matrix.CreateTranslation(currentPosition[2]);
            world[3] = initial[3] * Matrix.CreateTranslation(-currentPosition[3]) * Matrix.CreateRotationZ(-incline) * Matrix.CreateScale(currentScale[2]) * Matrix.CreateRotationY(currentRotation[2]) * Matrix.CreateRotationZ(incline) * Matrix.CreateTranslation(currentPosition[3]);
        }

        public void DrawLevelPlanets()
        {
            graphics.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            DrawModel(moon, world[1], view, projection, lightUp[0]);
            DrawModel(swamp, world[2], view, projection, lightUp[1]);
            DrawModel(dry, world[3], view, projection, lightUp[2]);
        }

        public void UpdateTitlePlanet(GameTime gameTime)
        {
            world[0] *= Matrix.CreateTranslation(-currentPosition[0]) * Matrix.CreateRotationZ(-incline) * Matrix.CreateRotationY(idleRotation) * Matrix.CreateRotationZ(incline) * Matrix.CreateTranslation(currentPosition[0]);
        }

        public void DrawTitlePlanet()
        {
            graphics.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            DrawModel(green, world[0], view, projection, false);
        }

        private void DrawModel(Model model, Matrix world, Matrix view, Matrix projection, bool lightUp)
        {
            foreach (ModelMesh mesh in model.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    if (lightUp)
                    {
                        effect.DirectionalLight0.DiffuseColor = new Vector3(1, 1, 1);
                        effect.DirectionalLight0.Direction = lightDirection;
                        //effect.DirectionalLight0.SpecularColor = new Vector3(1, 1, 1);
                    }
                    else
                    {
                        effect.EnableDefaultLighting();
                        //effect.DirectionalLight0.Enabled = false;
                        effect.DirectionalLight0.DiffuseColor = new Vector3(0.4f, 0.4f, 0.4f);
                        effect.DirectionalLight0.Direction = lightDirection;
                    }
                    //effect.AmbientLightColor = new Vector3(0.2f, 0.2f, 0.2f);
                    //effect.EmissiveColor = new Vector3(0.2f, 0, 0);
                    //effect.LightingEnabled = true;
                    //effect.DiffuseColor = new Vector3(255, 255, 255);
                    effect.World = mesh.ParentBone.Transform * world;
                    effect.View = view;
                    effect.Projection = projection;
                }
                mesh.Draw();
            }
        }
    }
}
